/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2007 Intel Corporation. All Rights Reserved.
//
//
*/

#include "umc_defs.h"
#if defined(UMC_ENABLE_AVS_SPLITTER)

#include "umc_sample_buffer_ex.h"
#include "umc_automatic_mutex.h"

namespace UMC
{

enum
{
    ALIGN_VALUE                 = 128,
    ALIGN_SAMPLE_VALUE          = 1024
};

SampleBufferEx::SampleBufferEx(void)
{

} // SampleBufferEx::SampleBufferEx(void)

SampleBufferEx::~SampleBufferEx(void)
{

} // SampleBufferEx::~SampleBufferEx(void)

Status SampleBufferEx::LockInputBuffer(MediaData *pDst, size_t nRequiredSize)
{
    AutomaticMutex guard(m_synchro);

    // check error(s)
    if (NULL == pDst)
        return UMC_ERR_NULL_PTR;
    if (NULL == m_pbFree)
        return UMC_ERR_NOT_INITIALIZED;

    // check buffer capacity
    if (nRequiredSize > m_Params.m_prefInputBufferSize)
    {
        Status umcRes;

        // try to re-initialize buffer with larger input size
        umcRes = Reallocate(nRequiredSize);
        if (UMC_OK != umcRes)
            return umcRes;
    }

    // just lock buffer
    return SampleBuffer::LockInputBuffer(pDst);

} // Status SampleBufferEx::LockInputBuffer(MediaData *pDst, size_t nRequiredSize)

Status SampleBufferEx::Reallocate(size_t nPrefInputSize)
{
    size_t nMaxSampleSize, nAllocate;
    MemID midAllocatedBuffer;
    Ipp8u *pbAllocatedBuffer;
    size_t nAllocatedBufferSize;

    // wait while the buffer become empty
    if (m_pSamples)
        return UMC_ERR_NOT_ENOUGH_BUFFER;

    m_Params.m_prefInputBufferSize = align_value<size_t> (nPrefInputSize, ALIGN_SAMPLE_VALUE);

    // allocate buffer
    nMaxSampleSize = IPP_MAX(m_Params.m_prefInputBufferSize, m_Params.m_prefOutputBufferSize) +
                             ALIGN_VALUE + sizeof(SampleInfo);
    nAllocate = nMaxSampleSize * IPP_MAX(m_Params.m_numberOfFrames, 3);
    if (UMC_OK != m_pMemoryAllocator->Alloc(&midAllocatedBuffer, nAllocate + ALIGN_VALUE, UMC_ALLOC_PERSISTENT, 16))
        return UMC_ERR_ALLOC;
    pbAllocatedBuffer = (Ipp8u *) m_pMemoryAllocator->Lock(midAllocatedBuffer);
    if (NULL == pbAllocatedBuffer)
    {
        m_pMemoryAllocator->Free(midAllocatedBuffer);
        return UMC_ERR_ALLOC;
    }
    nAllocatedBufferSize = nAllocate + ALIGN_VALUE;

    // release the previous buffer & set the new
    m_pMemoryAllocator->Unlock(m_midAllocatedBuffer);
    m_pMemoryAllocator->Free(m_midAllocatedBuffer);
    m_midAllocatedBuffer = midAllocatedBuffer;
    m_pbAllocatedBuffer = pbAllocatedBuffer;
    m_lAllocatedBufferSize = nAllocatedBufferSize;

    // align buffer
    m_pbBuffer = align_pointer<Ipp8u *> (m_pbAllocatedBuffer, ALIGN_VALUE);
    m_lBufferSize = nAllocate;

    m_pbFree = m_pbBuffer;
    m_lFreeSize = m_lBufferSize;
    m_pbUsed = m_pbBuffer;
    m_lUsedSize = 0;

    // save preferred size(s)
    m_lInputSize = m_Params.m_prefInputBufferSize;

    return UMC_OK;

} // Status SampleBufferEx::Reallocate(size_t nPrefInputSize)

} // namespace UMC

#endif // #if defined(UMC_ENABLE_AVS_SPLITTER)
